//*************************************************************************//
//*           _____   ____________            ______               __     *//
//*          / /__ \ / ____/ ____/           / ____/___  _________/ /     *//
//*     __  / /__/ // __/ / __/    ______   / /_  / __ \/ ___/ __  /      *//
//*    / /_/ // __// /___/ /___   /_____/  / __/ / /_/ / /  / /_/ /       *//
//*    \____//____/_____/_____/           /_/    \____/_/   \__,_/        *//
//*                                                                       *//
//*     Copyright (c) 2006 Ford Argentina. All Rights Reserved.           *//
//*                                                                       *//
//*************************************************************************//

package ar.com.ford.it.webengine.listener;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.RollingFileAppender;
import ar.com.ford.it.webengine.helper.FordAppDateFactory;
import ar.com.ford.it.webengine.metric.MetricsControllerFactory;
import ar.com.ford.it.webengine.persistence.PersistenceManagerProviderFactory;
import ar.com.ford.it.webengine.security.SecurityProviderFactory;
import ar.com.ford.it.webengine.security.SessionControllerFactory;
import ar.com.ford.it.webengine.settings.AppSettings;
import ar.com.ford.it.webengine.wslx.WslxUserFactory;
import com.ford.it.exception.FjfConfigurationException;
import com.ford.it.logging.ILogger;
import com.ford.it.logging.Level;
import com.ford.it.logging.LogFactory;
import com.ford.it.presentation.taglib.menu.Menu;
import com.ford.it.presentation.taglib.menu.MenuItem;

public class WebListener implements ServletContextListener {
	private static final String CLASS_NAME = WebListener.class.getName();
	private static final ILogger log = LogFactory.getInstance().getLogger(CLASS_NAME);
	
    protected ServletContext context;
    
    public static final String APP_CONFIG = "/resources/application.properties";

    public static final String MENU_DEFINITION_FILENAME="/resources/menu-definition.xml";
        
    protected AppSettings settings = AppSettings.getInstance();

	
	public void contextInitialized(ServletContextEvent event) {
		String METHOD_NAME = "contextInitialized";
		Properties configProps = null;
		
		try {
            System.out.println("Inicializando WebListener...");
            
            this.context = event.getServletContext();
            
            String pth = event.getServletContext().getRealPath("");
            // fix para websphere - elimina la ultima barra del path
            if (pth.toCharArray()[pth.length()-1] ==  File.separatorChar)
            	pth = pth.substring(0, pth.length()-1);
            
            settings.setAPP_PATH(pth);

            configProps = new Properties();

            // Cargar archivo de configuracion desde el classpath
            InputStream is = this.getClass().getResourceAsStream(APP_CONFIG);
            if (is == null) {
                throw new FileNotFoundException("File not found in classpath: "+APP_CONFIG);
            }
            configProps.load(is);
            
            settings.setAPP_NAME(configProps.getProperty("name").trim());
            event.getServletContext().setAttribute("appName", settings.getAPP_NAME());

            settings.setAPP_FULLNAME(configProps.getProperty("fullname").trim());
            event.getServletContext().setAttribute("appFullName", settings.getAPP_FULLNAME());

            settings.setAPP_SESSION_TIME_OUT(new Integer(configProps.getProperty("session-timeout").trim()));
            
            settings.setAPP_MAIL_SERVER(configProps.getProperty("smtp-server").trim());
            
            initAppenderLogger(configProps);
            
            // Inicializando Session Controller Factory
            SessionControllerFactory.init(configProps.getProperty("sessionController").trim());
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "UserAccessControl inicializado");

            // Inicializando security provider factory
            SecurityProviderFactory.init(configProps.getProperty("security-provider"));

            // Inicializando wslxuserfactory
            WslxUserFactory.init(configProps.getProperty("wslx"));
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "WslxUserFactory inicializada");


            // carga el template del menu y la estructura para validar el acceso a las acciones
            HashMap af = new HashMap();
            actionFilter(loadMenu(), af);
            settings.setActionFilter(af);
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Menu de la aplicacion cargado");
            
            
            // Inicializando FordAppDate
            FordAppDateFactory.init(configProps.getProperty("app-date").trim());
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "FordAppDateFactory inicializada");
            
            // Inicializando Metricas
            if ("yes".equalsIgnoreCase(configProps.getProperty("activeMetrics", "no"))) {
            	log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Inicializando metricas");
            	settings.setUseMetrics(true);
            	MetricsControllerFactory.init(configProps.getProperty("metricsController"));
            	MetricsControllerFactory.getMetricsController().initMetics();
            }
            
            
			//  Toplink Persistence Framework - accepted values: true | false
			if ("yes".equalsIgnoreCase(configProps.getProperty("fjf-persistence-facilities", "no"))) {
                log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Inicializando framework de persistencia...");
                settings.setFjf_persistence_facilities(true);
                PersistenceInitializer persistenceInit = new PersistenceInitializer();
                persistenceInit.initPersistenceFramework();
                
                PersistenceManagerProviderFactory.init(configProps.getProperty("persistenceProvider"));
                
                log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Framework de persistencia inicializado");
			}
			else {
                log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Framework de persistencia deshabilitado");
				settings.setFjf_persistence_facilities(false);	
			}

            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "*******************************************************");
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "************** Resumen de Inicializacion **************");
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Nombre", settings.getAPP_NAME());
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Nombre Completo", settings.getAPP_FULLNAME());
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Path", settings.getAPP_PATH());
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Session TimeOut", settings.getAPP_SESSION_TIME_OUT());
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Mail Server", settings.getAPP_MAIL_SERVER());
            if (settings.isFjf_persistence_facilities()) {
            	log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Toplink Persistence Framwork Facilities Activated");
            	log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Persistence Manager Provider", configProps.getProperty("persistenceProvider"));
            }
			if (settings.isUseMetrics())
				log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "Metrics Activated");
            log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "*******************************************************");
			log.logp(Level.INFO, CLASS_NAME, METHOD_NAME, "*******************************************************");
			
			
        }catch (Exception ex) {
            ex.printStackTrace();
            throw new Error(ex.getMessage());
        }
        
		log.exiting(CLASS_NAME, METHOD_NAME);
    }

	/**
	 * Inicializar logger
	 * @param configProps Properties de configuracion
	 */
    protected void initAppenderLogger(Properties properties) {
        String METHOD_NAME = "initAppenderLogger";
        PatternLayout pattern = new PatternLayout("%d{yyyy/MM/dd HH:mm:ss} - [" + settings.getAPP_NAME() + "] %-5p: %-8X{wslxuser} - %c{1} - %m\n");
        Appender appender;

        try {
            PropertyConfigurator.configure(settings.getAPP_PATH()+File.separator+"WEB-INF"+File.separator+"classes"+File.separator+"resources"+File.separator+"log4j.properties");
            RollingFileAppender rollFileappender = new RollingFileAppender();
            rollFileappender.setName("fileAppender");
            rollFileappender.setLayout(pattern);
            rollFileappender.setFile(settings.getAPP_PATH()+File.separator+"logs"+File.separator+settings.getAPP_NAME()+"_log");
            rollFileappender.setMaxFileSize(properties.getProperty("logger-maxsize").trim());
            rollFileappender.setMaxBackupIndex(Integer.parseInt(properties.getProperty("logger-maxbkps").trim()));
            rollFileappender.activateOptions();
            appender = rollFileappender;
        	System.out.println("Appender Logger inicializado!");
        }
        catch (Exception ex) {
            appender = new ConsoleAppender(pattern);
            String msg = "IOException on PrincipalAction.executeAction";
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, msg, ex);
        }

        Logger.getRootLogger().addAppender(appender);
        Logger.getRootLogger().setLevel(org.apache.log4j.Level.toLevel(properties.getProperty("logger-level").toUpperCase().trim()));

        log.logp(Level.INFO,CLASS_NAME, METHOD_NAME, "Appender: "+appender.getName());

        log.exiting(CLASS_NAME, METHOD_NAME);
    }	

    
	/**
	 * Cargar menu de la aplicacion
	 * @param config ApplicationConfig
	 * @return Menu Menu de la aplicacion
	 * @throws FjfConfigurationException
	 */
    protected Menu loadMenu() throws FjfConfigurationException {
        String METHOD_NAME = "loadMenu";
        log.entering(CLASS_NAME, METHOD_NAME);

        // load menu content from file using default property group name 'MenuRoot'
        Menu menu = new Menu();
        menu.load(MENU_DEFINITION_FILENAME);

        // store the menu instance in application context, using the menu name as key
        context.setAttribute(menu.getName(), menu);  
        AppSettings.getInstance().setApplicationMenuName(menu.getName());
        
        log.exiting(CLASS_NAME, METHOD_NAME);
		return menu;
    }    

    
    /**
     * Llenar un map con todos los actions que contiene el menu (Recursivo)
     */
    protected void actionFilter(MenuItem menu, HashMap afilter) {
    	String METHOD_NAME = "actionFilter";
    	log.entering(CLASS_NAME, METHOD_NAME);
		
		if (menu != null) {

			List menuItems = menu.getSubMenuItems();

			if (menuItems != null) {

				Iterator iterate = menuItems.iterator();

				while (iterate.hasNext()) {
					MenuItem mitem = (MenuItem)iterate.next();
					actionFilter(mitem, afilter);
					String actionName = mitem.getAction();
					if ((actionName != null) && (actionName.endsWith(".do")))
						afilter.put(actionName, mitem.getPrivilege());
				}

			}

		}
		
		log.exiting(CLASS_NAME, METHOD_NAME);
    }
    
	public void contextDestroyed(ServletContextEvent arg0) {
		
		MetricsControllerFactory.getMetricsController().endMetrics();
	}


}
